 /*
    *  Copyright 2004 Thevert Liu  <thevert.liu@gmail.com>
    *
    *  Licensed under the Apache License, Version 2.0 (the "License");
    *  you may not use this file except in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
#ifndef TEST_EXTRA_H
#define TEST_EXTRA_H


#include <cstdlib>
#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <XMLReaderParser.h>
#include <LibXML2Reader.h>
#include <fstream>
#include <xstring.h>

#include <XMLParserUnitTest.h>

//#include <XMLShell.h>
#include <handler.h>

namespace extra {

class ExtBlock : public IXMLElement
{
public:
    ExtBlock(const std::string& tagName="entry") : IXMLElement(tagName) 
    {
    }
    
    virtual ~ExtBlock() 
    {
    }
    
    void regist(IXMLShell& shell)  {
        shell.registAttribute("xmlns", 
                              new TAttribute<std::string>
                              (
                                this, 
                                &ExtBlock::setBaseURL,
                                &ExtBlock::getBaseURL,
                                false
                              )
                             ) ;
                             
        shell.registExtraBlock(new ExtraBlock (this, &ExtBlock::setExtra, &ExtBlock::getExtra)) ;
    }

    void setBaseURL(const std::string& url) {
        mBaseURL = url ;
    }    
    
    std::string* getBaseURL() {return mBaseURL.empty() ? NULL : &mBaseURL ;}
    
    void setExtra(const std::string& val) {
        mExtra = val ;
    }
    
    std::string* getExtra() {return mExtra.empty() ? NULL : &mExtra ;}
    
private:
    std::string mBaseURL ;
    std::string mExtra ;    
    
} ;


class Entry : public IXMLElement
{
public:
    Entry(const std::string& tagName="entry") : IXMLElement(tagName) 
    {
    }
    
    virtual ~Entry() 
    {
    }
    
    void regist(IXMLShell& shell)  {
        shell.registAttribute("id", new TAttribute<std::string>(this, &Entry::setID, &Entry::getID, true)) ;
        shell.registAttribute("template-id", new TAttribute<std::string>(this, &Entry::setTemplateID, &Entry::getTemplateID)) ;
        shell.registValue(new TValue<std::string> (this, &Entry::setDesc, &Entry::getDesc)) ;
    }   
    
    void setID(const std::string &id) 
    {
        mID = new std::string;
        *mID = id ;
        s3debug << "Set Entry:" << getTagName() << " ID:" << *mID << ENDL ;
    }

    std::string* getID() {return mID;}
    
    void setTemplateID(const std::string& id) 
    {
        mTemplateID =  new std::string;
        *mTemplateID = id ;
        
        s3debug << "Set Entry:" << getTagName() << " Template-ID:" << *mTemplateID << ENDL ;
    }
    
    std::string* getTemplateID() {return mTemplateID;}
    
    void setDesc(const std::string& desc) 
    {
        mDesc = new std::string;
        *mDesc = desc ;
//        s3debug << "desc len: " << desc.length() << desc << ENDL ;
//        s3debug << "Set Entry:" << getTagName() << " Desc:" << mDesc->length() << *mDesc << ENDL ;
    }

    std::string* getDesc() 
    {
//        s3debug << "Get desc:" << *mDesc << ENDL ;
        return mDesc;
    }
    
private:
    std::string* mID ;
    std::string* mTemplateID ;
    std::string* mDesc ; 
} ;

class Feed : public IXMLElement
{
public:
    Feed(const std::string& tagName="feed") :IXMLElement(tagName) 
    {
    }
    
    void regist(IXMLShell& shell)  {
        shell.registAttribute
          ( 
            "id", 
            new TAttribute<std::string>
            (
                (Feed*)this, 
                &Feed::setID, 
                &Feed::getID,
                true
            )
          ) ;
        
        shell.registElement
          (
            "entry", 
            new TElements<Entry>
            (
                this 
              , &Feed::setEntry
              , &Feed::getEntries
              , 0 
              , (unsigned int)-1
            )
          ) ;
            
        shell.registElement
          (
            "ext-block", 
            new TElement<ExtBlock>
            (
                this 
              , &Feed::setExtra
              , &Feed::getExtra
              , false 
            )
          ) ;
    }
    
    TContainer<Entry>& getEntries() {return mEntries;}
    
    void setEntry(Entry* entry) {
        mEntries.push(entry) ;
        s3debug << "Set Feed:" << getTagName() << " Entry" << ENDL ;
    }

    std::string* getID()  {return mID;}

    void setID(const std::string& id) {
        mID=new std::string(id);
        s3debug << "Set Feed:" << getTagName() << " ID:" << id << ENDL ;
    }
    
    void setExtra(ExtBlock* b) {mExtra=b;}
    ExtBlock* getExtra() {return mExtra;}
    
private:    

    std::string* mID ;
    
    TContainer<Entry> mEntries ;
    
    ExtBlock * mExtra ;
} ;

}

class TestExtra : XMLParserUnitTest
{
public:
    static bool excute() {
        extra::Feed feed("feed") ;
        doTest("feed_extra.xml", feed, std::cout) ;

        return true ;
    }
} ;


#endif

